<?php
namespace App\Services;

use App\Api\Models\SellMaterielPrepareOutLogModel;
use App\V3\V3_1\Models\SerialNumberModel;
use App\Api\Models\StorageBatchModel;
use App\Api\Services\MaterielService;
use App\V3\Api\Services\ShelfService;
use App\Models\AdminModel;
use App\Models\LogInstorageModel;
use App\Models\LogOutstorageModel;
use App\Models\LogOutPackageModel;
use App\Models\MaterielTypeModel;
use App\Models\StorageModel;
use Illuminate\Support\Facades\DB;
use App\Models\StorageManageModel;
use Illuminate\Support\Facades\Log;

class StorageManageService {
    //库存查看列表
    static public function list($parentId, $data)
    {
        $keyword = empty($data['keyword'])?'':$data['keyword'];
        $condition = [];
        if(!empty($data['materiel_class_id'])) {
            $condition['d.materiel_class_id'] = ['EQ' => $data['materiel_class_id']];
        }

        $result = StorageManageModel::list($parentId, $keyword, $condition, $data);

        return $result;
    }

    //导出
    static public function export($userId, $data)
    {
        $adminInfo = AdminModel::where('id', $userId)->first();
        if($adminInfo['parent_id'] != 0) {
            $parentId = $adminInfo['parent_id'];
        }
        else {
            $parentId = $userId;
        }

        $result = StorageManageModel::export($parentId, $data);

        $fileName = '库存报表_'.date('Y-m-d').'.csv';      //文件名
        set_time_limit(0);
        ini_set('memory_limit', '1024M');

        header('Content-Type: application/vnd.ms-excel; charset=utf-8');    //输出文件类型
        header('Content-Disposition: attachment;filename="'.$fileName.'"');    //输出文件名
        header('Cache-Control: max-age=0');    //强制每次请求直接发送给源服务器，而不经过本地缓存版本的校验

        // 设置标题
        $title = [
            "物料编号",
            "物料名",
            "物料型号",
            "物料一级分类名",
            "物料一级分类编号",
            "物料二级分类名",
            "物料二级分类编号",
            "仓库名",
            "仓库地址",
            "物料成本",
            "库存数",
        ];

        $fp = fopen('php://output', 'a');
        fputcsv($fp, $title);

        foreach($result as $k => $v) {
            if($k/300 == 0) {
                ob_flush();
                flush();
            }

            if(mb_detect_encoding($v->materiel_name, 'utf-8', true)) {
                Log::debug('导出1');
            }

            if(mb_detect_encoding($v->materiel_name, 'gbk', true)) {
                Log::debug('导出2');
            }

            $arr = [];
            $arr[] = empty($v->materiel_no)?'暂无':$v->materiel_no;
            $arr[] = mb_convert_encoding($v->materiel_name, 'utf-8', 'auto');
            $arr[] = mb_convert_encoding($v->type_name, 'utf-8', 'auto');
            $arr[] = mb_convert_encoding($v->f_class_name, 'utf-8', 'auto');
            $arr[] = empty($v->f_class_no)?'暂无':$v->f_class_no;
            $arr[] = mb_convert_encoding($v->s_class_name, 'utf-8', 'auto');
            $arr[] = empty($v->s_class_no)?'暂无':$v->s_class_no;
            $arr[] = mb_convert_encoding($v->storage_name, 'utf-8', 'auto');
            $arr[] = mb_convert_encoding($v->storage_address, 'utf-8', 'auto');
            $arr[] = $v->materiel_mean_cost;
            $arr[] = $v->in_storage_num;

            fputcsv($fp, $arr);
        }

        fclose($fp);

        return true;
    }

    static public function exportData($userId, $data)
    {
        $adminInfo = AdminModel::where('id', $userId)->first();
        if($adminInfo['parent_id'] != 0) {
            $parentId = $adminInfo['parent_id'];
        }
        else {
            $parentId = $userId;
        }

        return StorageManageModel::export($parentId, $data);
    }

    /**
     * @入库
     * @created 在 2021/11/29 19:00 创建
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param array $data['content] 入库物料商品信息
     * @param array $data['content]['name'] 物料名称
     * @param array $data['content]['type_name'] 物料名称
     * @param array $data['content]['warehouse'] 仓库名
     * @param array $data['content]['warehouse_id'] 仓库主键id
     * @param array $data['content]['num] 操作数量
     * @param array $data['in_storage_time] 入库时间
     * @param array $data['all_id_type] 单据类型;0:无;1:报溢;2:退货;3:采购;
     * @param array $data['all_id] 单据id
     * @param array $data['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function inStorage($userId, $mainId, $data,$flag = 0)
    {
        $logInstorageData = [];//入库操作记录数据
        $instorageNumsData = [];//库存数据信息-更新库存
        $arr = [];

        foreach($data['content'] as $key => $value) {
            //为了兼容版本 判断shelf_id 和location_id
            if(empty($value['shelf_id']) || empty($value['location_id'])){
               /*  $shelf_id = ShelfService::get_default($value['warehouse_id'])['id'];
                $location_id = ShelfService::get_default($shelf_id,2)['id']; */
                $sfData = ShelfService::get_default($value['warehouse_id']);
                if(!empty($sfData)){
                    $shelf_id = $sfData['id'];
                    $lData = ShelfService::get_default($shelf_id,2);
                    $location_id = $lData['id'];
                }else{
                    $shelf_id = 0;
                    $location_id = 0;
                    $value['shelf_id']=0;
                    $value['location_id']=0;
                }
            }else{
                $shelf_id = $value['shelf_id'];
                $location_id = $value['location_id'];
            }

            //物料商品信息
            $materielTypeInfo = MaterielTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no',
                'c.id as first_class'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                ->where([
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                ])
                ->first();

            if(empty($materielTypeInfo)) {
                throw new \Exception('商品信息不存在，无法入库');
            }

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'main_id' => $mainId,
                'shelf_id' => $shelf_id,
                'location_id' => $location_id
            ])->first();

            if(empty($storageManageInfo)) {
                $arr[] = [
                    'first_class' => $materielTypeInfo['first_class'],
                    'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                    'materiel_class_name' => $materielTypeInfo['class_name'],
                    'materiel_class_no' => $materielTypeInfo['class_no'],
                    'type_id' => $materielTypeInfo['id'],
                    'materiel_name' => $materielTypeInfo['materiel_name'],
                    'type_name' => $materielTypeInfo['type_name'],
                    'materiel_no' => $materielTypeInfo['materiel_no'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $value['num'],
                    'virtual_storage_num' => $value['num'],
                    'main_id' => $mainId,
                    'in_storage_time' => time(),

                    'shelf_id' => $shelf_id,
                    'location_id' => $location_id,
                    'serial_no' => empty($value['serial_no'])?'':$value['serial_no'],

                ];

                MessageService::sendInSms(
                    '',
                    $materielTypeInfo['materiel_name'],
                    $materielTypeInfo['type_name'],
                    $storageInfo['id'],
                    $storageInfo['storage_name'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $value['num'],
                    $value['num']
                );
            }
            else {
                if(!empty($value['serial_no'])){
                     $instorageNumsData[] = [
                                    'id' => $storageManageInfo['id'],//库存主键id
                                    'in_storage_num' => $value['num'],//入库数量
                                    'type_id' => $materielTypeInfo['id'],
                                    'cost' => $storageManageInfo['materiel_mean_cost'],
                                    'serial_no' => $value['serial_no'],
                                ];
                }else{
                    $instorageNumsData[] = [
                        'id' => $storageManageInfo['id'],//库存主键id
                        'in_storage_num' => $value['num'],//入库数量
                        'type_id' => $materielTypeInfo['id'],
                        'cost' => $storageManageInfo['materiel_mean_cost']
                    ];
                }

                MessageService::sendInSms(
                    '',
                    $materielTypeInfo['materiel_name'],
                    $materielTypeInfo['type_name'],
                    $storageInfo['id'],
                    $storageInfo['storage_name'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                   $value['num'],
                    $value['num'] + $storageManageInfo['in_storage_num']
                );

                $logInstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//当前库存id
            }

            $logInstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logInstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $logInstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $logInstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号
            $logInstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logInstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $logInstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $logInstorageData[$key]['type'] = 0;//入库日志类型;0:入库;1:调拨入库;2:直接入库;
            $logInstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logInstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
            $logInstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $logInstorageData[$key]['last_storage_id'] = 0;//调拨前所在仓库id
            $logInstorageData[$key]['operate_num'] = $value['num'];//操作数量
            $logInstorageData[$key]['last_storage_num'] = empty($storageManageInfo['in_storage_num'])?0:$storageManageInfo['in_storage_num'];//操作前库存数
            $logInstorageData[$key]['materiel_mean_cost'] = empty($storageManageInfo['materiel_mean_cost'])?0:$storageManageInfo['materiel_mean_cost'];//物料均价
            if(!empty($storageManageInfo)){
            $logInstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] + $value['num'];//操作后库存数
            }else{
            $logInstorageData[$key]['next_storage_num'] = $value['num'];//操作后库存数
            }
            $logInstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报溢;2:退货;3:采购;
            $logInstorageData[$key]['in_storage_time'] = strtotime($data['in_storage_time']);//入库时间
            $logInstorageData[$key]['all_id'] = $data['all_id'];//单据id
            $logInstorageData[$key]['user_id'] = $userId;//操作人用户id
            $logInstorageData[$key]['main_id'] = $mainId;//主账号id
            $logInstorageData[$key]['remark'] = empty($data['remark'])?'':$data['remark'];
            $logInstorageData[$key]['created_at'] = time();
            $logInstorageData[$key]['serial_number'] = !empty($value['serial_no'])?$value['serial_no']:'';
            $logInstorageData[$key]['shelf_id'] = $shelf_id;
            $logInstorageData[$key]['location_id'] = $location_id;

        }

        DB::beginTransaction();

        try {

            if(!empty($instorageNumsData)) {

                //更新库存总数
                foreach($instorageNumsData as $key => $value) {
                    $bool = StorageManageModel::where('id', $value['id'])
                        ->update([
                            'in_storage_num' => DB::raw('in_storage_num + '.$value['in_storage_num']),
                            'virtual_storage_num' => DB::raw('virtual_storage_num + '.$value['in_storage_num']),
                            'delete_flag' => 0
                        ]);

                    $batchTitle = empty($data['batch_title']) ? '' : $data['batch_title'];
                    $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                        ->where('batch_no', $batchNo)->first();

                    do {
                        $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                    }
                    while(!empty($checkBatchNo));

                    $batchId = MaterielService::createBatchInfoGetId(
                        $batchNo,
                        $value['id'],
                        $value['cost'],
                        $value['in_storage_num'],
                        0,
                        $mainId
                    );
                    if(!$flag){
                        if(!empty($value['serial_no'])){
                            //处理序列号
                            $serial_no_res = SerialNumberModel::inSerialNumber($mainId,$value['serial_no'],$value['in_storage_num'],$value['type_id'],$value['id'],$batchNo);
                            if(!empty($serial_no_res['code'])){
                                return ['code' => 1, 'msg' => $serial_no_res['msg'], 'data' => ''];
                            }
                        }
                    }
                }
            }

            if(!empty($arr)) {
                foreach($arr as $v) {
                    foreach($logInstorageData as $k1 => $v1) {
                        if($v1['materiel_type_id'] == $v['type_id']) {
                            $arr = [
                                'materiel_class_id' => $v['materiel_class_id'],
                                'materiel_class_name' => $v['materiel_class_name'],
                                'materiel_class_no' => $v['materiel_class_no'],
                                'type_id' => $v['type_id'],
                                'materiel_name' => $v['materiel_name'],
                                'type_name' => $v['type_name'],
                                'materiel_no' => $v['materiel_no'],
                                'storage_id' => $v['storage_id'],
                                'storage_name' => $v['storage_name'],
                                'storage_address' => $v['storage_address'],
                                'in_storage_num' => $v['in_storage_num'],
                                'virtual_storage_num' => $v['virtual_storage_num'],
                                'main_id' => $mainId,
                                'in_storage_time' => time(),

                                'shelf_id' => $v['shelf_id'],
                                'location_id' => $v['location_id'],
                            ];

                            $batchTitle = empty($data['batch_title']) ? '' : $data['batch_title'];
                            $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                            $checkBatchNo = StorageBatchModel::where('main_id', $mainId)
                                ->where('batch_no', $batchNo)->first();

                            do {
                                $batchNo = $batchTitle.date('YmdHis', time()).mt_rand(1000, 9999).'0';
                            }
                            while(!empty($checkBatchNo));

                            $insertId = StorageManageModel::insertGetId($arr);

                            $logInstorageData[$k1]['curr_storage_manage_id'] = $insertId;

                            $batchId = MaterielService::createBatchInfoGetId(
                                $batchNo,
                                $insertId,
                                0,
                                $v['in_storage_num'],
                                0,
                                $mainId
                            );

                            $logInstorageData[$k1]['batch_id'] = $batchId;
                            if(!$flag){
                                if(!empty($v['serial_no'])){
                                    //处理序列号
                                    $serial_no_res = SerialNumberModel::inSerialNumber($mainId,$v['serial_no'],$v['in_storage_num'],$v['type_id'],$insertId,$batchNo);
                                    if(!empty($serial_no_res['code'])){
                                        return ['code' => 1, 'msg' => $serial_no_res['msg'], 'data' => ''];
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if(!empty($logInstorageData)){
                foreach ($logInstorageData as &$lv){
                    if(empty($lv['batch_id'])) $lv['batch_id'] = 0;
                }
            }
            //生成入库操作记录
            $bool= LogInstorageModel::insert($logInstorageData);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollback();
            Log::debug('非采购入库：'.var_export($e->getMessage(), true));
        }
    }

    /**
     * @出库
     * @created 在 2021/11/29 19:08 创建
     * @param $userId 操作人用户id
     * @param $mainId 主账号id
     * @param $data['content] 出库物料商品信息
     * @param $data['content]['name] 物料名称
     * @param $data['content]['price] 单价
     * @param $data['content]['type_name] 物料型号
     * @param $data['content]['warehouse] 仓库名
     * @param $data['content]['warehouse_id] 仓库主键id
     * @param $data['content]['num] 出库操作数量
     * @param $data['all_id_type] 单据类型;0:无;1:报损;2:销售;
     * @param $data['all_id] 单据id
     * @param $data['out_storage_time] 出库时间
     * @param $data['remark] 备注
     * @return array
     * @author: Sun Wu
     */
    static public function outStorage($userId, $mainId, $data, $sellId = '')
    {
        $logOutstorageData = [];//出库操作记录数据
        $outstorageNumsData = [];//库存数据信息-更新库存
        $returnData = [];//返回数据
        foreach($data['content'] as $key => $value) {
            //物料商品信息
            $materielTypeInfo = MaterielTypeModel::select(
                'a.id',
                'materiel_name',
                'type_name',
                'materiel_no',
                'b.id as materiel_class_id',
                'b.class_name',
                'b.class_no'
            )
                ->from('materiel_type as a')
                ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                ->where([
                    'materiel_name' => $value['name'],
                    'type_name' => $value['type_name'],
                    'a.main_id' => $mainId,
                    'a.delete_flag' => 0,
                ])
                ->first();

            if(empty($materielTypeInfo)) {
                return ['code' => 1, 'msg' => '物料商品`'.$value['name'].'-'.$value['type_name'].'`不存在', 'data' => ''];
            }

            //仓库信息
            $storageInfo = StorageModel::where([
                'storage_name' => $value['warehouse'],
                'id' => $value['warehouse_id'],
                'main_id' => $mainId,
                'delete_flag' => 0,
            ])->first();

            if(empty($storageInfo)) {
                return ['code' => 1, 'msg' => '仓库`'.$value['warehouse'].'`不存在', 'data' => ''];
            }

            //物料当前库存信息
            $storageManageInfo = StorageManageModel::where([
                'type_id' => $materielTypeInfo['id'],
                'storage_id' => $storageInfo['id'],
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],
                'main_id' => $mainId,
                'delete_flag' => 0
            ])->first();

            //检查库存中是否存在该物料
            if(empty($storageManageInfo)) {
                return ['code' => 1, 'msg' => '库存中物料`'.$value['name'].'-'.$value['type_name'].'`不存在', 'data' => ''];
            }

            if($storageManageInfo['in_storage_num'] < $value['num']) {
                return ['code' => 1, 'msg' => '当前库存剩余数量不足，无法完成出库', 'data' => ''];
            }

            $logOutPackageData[$key]['storage_manage_id'] = $storageManageInfo['id'];//库存id
            $logOutPackageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logOutPackageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logOutPackageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logOutPackageData[$key]['out_time'] = strtotime(date('Y-m-d'));//实际出库时间
            $logOutPackageData[$key]['mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价

            $price = empty($value['price'])?0:$value['price'];

            $logOutPackageData[$key]['price'] = $data['all_id_type'] == 1?$storageManageInfo['materiel_mean_cost']:$price;
            $logOutPackageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
            $logOutPackageData[$key]['all_id'] = $data['all_id'];//单据id
            $logOutPackageData[$key]['user_id'] = $userId;
            $logOutPackageData[$key]['main_id'] = $mainId;
            $logOutPackageData[$key]['created_at'] = time();
            $logOutPackageData[$key]['num'] = $value['num'];//操作数量

            $logOutstorageData[$key]['materiel_type_id'] = $materielTypeInfo['id'];//物料id
            $logOutstorageData[$key]['materiel_name'] = $materielTypeInfo['materiel_name'];//物料名称
            $logOutstorageData[$key]['type_name'] = $materielTypeInfo['type_name'];//物料型号
            $logOutstorageData[$key]['materiel_no'] = $materielTypeInfo['materiel_no'];//物料编号
            $logOutstorageData[$key]['materiel_class_id'] = $materielTypeInfo['materiel_class_id'];//物料二级分类主键名称
            $logOutstorageData[$key]['materiel_class_name'] = $materielTypeInfo['class_name'];//物料二级分类名称
            $logOutstorageData[$key]['materiel_class_no'] = $materielTypeInfo['class_no'];//物料二级分类编号
            $logOutstorageData[$key]['curr_storage_manage_id'] = $storageManageInfo['id'];//库存id
            $logOutstorageData[$key]['type'] = 0;//type;0:出库;1:调出;
            $logOutstorageData[$key]['storage_id'] = $storageInfo['id'];//仓库主键id
            $logOutstorageData[$key]['storage_name'] = $storageInfo['storage_name'];//仓库名
            $logOutstorageData[$key]['storage_address'] = $storageInfo['storage_address'];//仓库地址
            $logOutstorageData[$key]['next_storage_id'] = 0;//调拨出库目标仓库主键id
            $logOutstorageData[$key]['operate_num'] = $value['num'];//操作数量
            $logOutstorageData[$key]['last_storage_num'] = $storageManageInfo['in_storage_num'];//操作前库存数
            $logOutstorageData[$key]['materiel_mean_cost'] = $storageManageInfo['materiel_mean_cost'];//物料均价
            $logOutstorageData[$key]['next_storage_num'] = $storageManageInfo['in_storage_num'] - $value['num'];//操作后库存数
            $logOutstorageData[$key]['all_id_type'] = $data['all_id_type'];//单据类型;0:无;1:报损;2:销售;
            $logOutstorageData[$key]['all_id'] = $data['all_id'];//单据id
            $logOutstorageData[$key]['out_storage_time'] = strtotime($data['out_storage_time']);//出库时间
            $logOutstorageData[$key]['fact_out_time'] = strtotime(date('Y-m-d'));//实际出库时间
            $logOutstorageData[$key]['remark'] = empty($data['remark'])?'':$data['remark'];//备注
            $logOutstorageData[$key]['user_id'] = $userId;//操作人用户id
            $logOutstorageData[$key]['main_id'] = $mainId;//主账号id
            $logOutstorageData[$key]['created_at'] = time();

            $outstorageNumsData[] = [
                'id' => $storageManageInfo['id'],//库存主键id
                'in_storage_num' => $storageManageInfo['in_storage_num'],//当前库存数
                'materiel_name' => $materielTypeInfo['materiel_name'],//出库物料名
                'type_name' => $materielTypeInfo['type_name'],//出库物料型号
                'alert_num' => $storageManageInfo['alert_num'],//低库存预警数
                'storage_name' => $storageInfo['storage_name'],
                'materiel_no' => $materielTypeInfo['materiel_no'],//出库物料型号
                'num' => $value['num'],//出库数量
            ];

            $returnData[] = [
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名
                'type_name' => $materielTypeInfo['type_name'],//物料型号
                'warehouse' => $storageInfo['storage_name'],//仓库名
                'warehouse_id' => $storageInfo['id'],//仓库主键id
                'cost_price' => $storageManageInfo['materiel_mean_cost'],//平均成本价
            ];
        }

        DB::beginTransaction();

        try {
            //生成入库操作记录
            LogOutstorageModel::insert($logOutstorageData);

            LogOutPackageModel::insert($logOutPackageData);

            //更新库存总数
            foreach($outstorageNumsData as $val) {
                StorageManageModel::where('id', $val['id'])->decrement('in_storage_num', $val['num']);

                //验证是否有预出库，有则跳过此步骤
                $prepareInfo = SellMaterielPrepareOutLogModel::where('sell_id', $sellId)
                    ->where('materiel_type_id', $val['type_id'])->first();
                if(empty($prepareInfo)) {
                    StorageManageModel::where('id', $val['id'])->decrement('virtual_storage_num', $val['num']);
                }

                MessageService::sendAlertSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $val['alert_num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageInfo['id'],
                    $val['storage_name'],
                    $val['num']
                );

                MessageService::sendShortSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $val['storage_name'],
                    $storageInfo['id']
                );

                MessageService::sendOutSms(
                    $val['materiel_name'],
                    $val['type_name'],
                    $val['in_storage_num'] - $val['num'],
                    $val['storage_name'],
                    $val['num'],
                    $datas=['user_id'=>$userId,'main_id' => $mainId],
                    $storageInfo['id'],
                    $val['alert_num'],
                );
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => $returnData];
        }
        catch(\Exception $e) {
            DB::rollback();
            Log::debug('出库：'.var_export($e->getMessage(), true));
        }
    }

    //直接入库(新建入库)
    static public function directInStorage($data)
    {
        $data['alert_num'] = $data['status'] == 1?$data['alert_num']:0;
        $data['remark'] = empty($data['remark'])?'':$data['remark'];

        //没有传货架库位，使用默认货架库位
        if(empty($data['shelf_id']) || empty($data['location_id'])){
           /*  $shelf_id = ShelfService::get_default($data['storage_id'])['id'];
            $location_id = ShelfService::get_default($shelf_id,2)['id']; */

            $sfData = ShelfService::get_default($data['storage_id']);
            if(!empty($sfData)){
                $shelf_id = $sfData['id'];
                $lData = ShelfService::get_default($shelf_id,2);
                $location_id = $lData['id'];
            }else{
                $shelf_id = 0;
                $location_id = 0;
                $data['shelf_id']=0;
                $data['location_id']=0;
            }
        }else{
            $shelf_id = $data['shelf_id'];
            $location_id = $data['location_id'];
        }

        $materielTypeInfo = MaterielTypeModel::select(
            'a.id',
            'materiel_name',
            'type_name',
            'materiel_no',
            'b.id as materiel_class_id',
            'b.class_name',
            'b.class_no',
            'c.id as first_class',
            'cost'
        )
            ->from('materiel_type as a')
            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
            ->where([
                'materiel_name' => $data['materiel_name'],
                'type_name' => $data['type_name'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0,
            ])
            ->first();

        if(empty($materielTypeInfo)) {
            return ['code' => 1, 'msg' => '物料`'.$data['materiel_name'].'-'.$data['type_name'].'`不存在', 'data' => ''];
        }

        //仓库信息
        $storageInfo = StorageModel::where([
            'storage_name' => $data['storage_name'],
            'id' => $data['storage_id'],
            'main_id' => $data['main_id'],
            'delete_flag' => 0,
        ])->first();

        if(empty($storageInfo)) {
            return ['code' => 1, 'msg' => '仓库`'.$data['storage_name'].'`不存在', 'data' => ''];
        }

        //检查库存信息
        $checkStorageManage = StorageManageModel::where([
            'type_id' => $materielTypeInfo['id'],
            'storage_id' => $data['storage_id'],
            'main_id' => $data['main_id'],
//            'shelf_id' => $shelf_id,
//            'location_id' => $location_id,
        ])->first();

        $newStorageManageInfo = [];//新物料入库
        $updateInStorageNum = [];//已有物料入库
        if(empty($checkStorageManage)) {
            $newStorageManageInfo = [
                'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
                'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
                'materiel_class_no' => empty($materielTypeInfo['class_no'])?'':$materielTypeInfo['class_no'],//物料二级分类名称
                'type_id' => $materielTypeInfo['id'],//物料id
                'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
                'type_name' => $materielTypeInfo['type_name'],//物料型号名称
                'materiel_no' => empty($materielTypeInfo['materiel_no'])?'':$materielTypeInfo['materiel_no'],//物料编号
                'materiel_mean_cost' => $materielTypeInfo['cost'] == 0?0:$materielTypeInfo['cost'],
                'storage_id' => $storageInfo['id'],//仓库id
                'storage_name' => $storageInfo['storage_name'],//仓库名
                'storage_address' => $storageInfo['storage_address'],//仓库地址
                'in_storage_num' => $data['num'],//采购单内物料商品入库数量
                'virtual_storage_num' => $data['num'],
                'main_id' => $data['main_id'],//主账号id
                'in_storage_time' => time(),//入库时间
                'alert_num' => $data['alert_num'],
                'created_at' => time(),

                'shelf_id' => $shelf_id,
                'location_id' => $location_id,
            ];

            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                $data['num'],
                $data['num']
            );
        }
        else {
            $updateInStorageNum = [
                'id' => $checkStorageManage->id,
                'in_storage_num' => $data['num'],
                'alert_num' => $data['alert_num'],
                'remark' => $data['remark'],
                'materiel_mean_cost' => $materielTypeInfo['cost'],
            ];

            MessageService::sendInSms(
                '无',
                $materielTypeInfo['materiel_name'],
                $materielTypeInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                $data['num'],
                $checkStorageManage['in_storage_num'] + $data['num'],
            );
        }

        $inStorageNum = !empty($checkStorageManage)?$checkStorageManage['in_storage_num']:0;

        //入库操作记录
        $logInStorage = [
            'type' => 2,//日志类型;0:入库;1:调拨入库;2:直接入库;
            'storage_id' => $storageInfo['id'],//入库目标仓库id
            'storage_name' => $storageInfo['storage_name'],//仓库名
            'storage_address' => $storageInfo['storage_address'],//仓库地址
            'last_storage_id' => 0,//调拨前所在仓库id
            'materiel_class_id' => $materielTypeInfo['materiel_class_id'],//物料二级分类id
            'materiel_class_name' => $materielTypeInfo['class_name'],//物料二级分类名称
            'materiel_class_no' => empty($materielTypeInfo['class_no'])?'':$materielTypeInfo['class_no'],//物料二级分类名称
            'materiel_type_id' => $materielTypeInfo['id'],//物料id
            'materiel_name' => $materielTypeInfo['materiel_name'],//物料名称
            'type_name' => $materielTypeInfo['type_name'],//物料型号名称
            'materiel_no' => empty($materielTypeInfo['materiel_no'])?'':$materielTypeInfo['materiel_no'],//物料编号
            'operate_num' => $data['num'],//操作数量
            'last_storage_num' => $inStorageNum,//操作前库存数
            'next_storage_num' => $inStorageNum + $data['num'],//操作后库存数
            'materiel_mean_cost' => 0,//物料均价
            'in_storage_time' => time(),//入库时间
            'remark' => $data['remark'],//备注
            'all_id_type' => 0,//单据类型;0:无;1:报溢;2:报损;3:采购;
            'all_id' => 0,//单据id
            'user_id' => $data['user_id'],//操作人id
            'main_id' => $data['main_id'],//主账号id
            'created_at' => time(),

            'shelf_id' => $shelf_id,
            'location_id' => $location_id,
        ];

        DB::beginTransaction();

        try {
            $meanCost = 0;
            if(!empty($newStorageManageInfo)) {
                $meanCost = $newStorageManageInfo['materiel_mean_cost'];
                $newStorageManageId = StorageManageModel::insertGetId($newStorageManageInfo);
            }

            if(!empty($updateInStorageNum)) {
                StorageManageModel::where('id', $updateInStorageNum['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num + '.$data['num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num + '.$data['num']),
                        'alert_num' => $data['alert_num'],
                        'materiel_mean_cost' => $updateInStorageNum['materiel_mean_cost'],
                        'delete_flag' => 0
                    ]);

                $meanCost =  $updateInStorageNum['materiel_mean_cost'];
                $newStorageManageId = $updateInStorageNum['id'];
            }

            $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';

            do{
                $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';
            }
            while(!empty(StorageBatchModel::where('batch_no', $batchNo)->first()));

            StorageBatchModel::insert([
                'batch_no' => $batchNo,
                'storage_manage_id' => $newStorageManageId,
                'batch_num' => $data['num'],
                'batch_left_num' => $data['num'],
                'batch_cost' => $meanCost,
                'materiel_id' => 0,
                'main_id' => $data['main_id'],
                'created_at' => time()
            ]);

            $logInStorage['curr_storage_manage_id'] = $newStorageManageId;

            LogInstorageModel::insert($logInStorage);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch (\Exception $e) {
            DB::rollback();
            Log::debug('新建入库(直接入库：'.var_export($e->getMessage(), true));
        }
    }

    //删除库存信息
    static public function del($data)
    {
        $storageManageInfo = StorageManageModel::where('id', $data['id'])->first();

        if($storageManageInfo['in_storage_num'] != 0) {
            return ['code' => 1, 'msg' => '当商品库存数为0时才可删除，当前库存数为：'.$storageManageInfo['in_storage_num'], 'data' => ''];
        }

        StorageManageModel::where('id', $data['id'])
            ->update(['delete_flag' => 1]);

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    static public function allocate($data)
    {
        //需调拨物料信息
        $storageManageInfo = StorageManageModel::select(
            'a.id',
            'a.alert_num',
            'a.materiel_class_id',
            'a.materiel_mean_cost',
            'a.in_storage_num',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'a.type_id',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_no',
            'a.storage_id',
            'd.storage_name',
            'd.storage_address',
            'e.id as first_class',
            'virtual_storage_num'
        )
        ->from('storage_manage as a')
        ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
        ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
        ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
        ->leftJoin('materiel_class as e', 'e.id', '=', 'b.parent_id')
        ->where([
            'a.id' => $data['id'],
            'a.main_id' => $data['main_id'],
            'a.delete_flag' => 0
        ])->first();

        if(empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '库存中不存在的物料，无法完成调拨', 'data' => ''];
        }

        if($storageManageInfo['storage_id'] == $data['storage_id']) {
            return ['code' => 1, 'msg' => '禁止同库调拨', 'data' => ''];
        }

        //调入仓库信息
        $storageInfo = StorageModel::where([
            'id' => $data['storage_id'],
            'main_id' => $data['main_id'],
        ])->first();

        if(empty($storageInfo)) {
            return ['code' => 1, 'msg' => '调入仓库不存在，无法完成调拨', 'data' => ''];
        }

        if($storageManageInfo['in_storage_num'] < $data['allocate_num']) {
            return ['code' => 1, 'msg' => '调拨数量超出实际库存数，无法完成调拨,当前库存数为:'.$storageManageInfo['in_storage_num'], 'data' => ''];
        }

        //检查调入仓库是否存在相同物料商品
        $checkStorageManageInfo = StorageManageModel::where([
            'materiel_class_id' => $storageManageInfo['materiel_class_id'],
            'type_id' => $storageManageInfo['type_id'],
            'storage_id' => $storageInfo['id'],
            'main_id' => $data['main_id'],
        ])
        ->where('id', '!=', $storageManageInfo['materiel_class_id'])->first();

        DB::beginTransaction();

        try {
            $meanCost = 0;
            if(!empty($checkStorageManageInfo)) {
                $meanCost = $checkStorageManageInfo['materiel_mean_cost'];
                StorageManageModel::where('id', $checkStorageManageInfo['id'])->update([
                    'in_storage_num' => DB::raw('in_storage_num +'.$data['allocate_num']),
                    'virtual_storage_num' => DB::raw('virtual_storage_num +'.$data['allocate_num']),
                    'delete_flag' => 0
                ]);
                $newStorageId = $checkStorageManageInfo['id'];
            }
            else {
                $meanCost = $storageManageInfo['materiel_mean_cost'];
                $arr = [
                    'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                    'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                    'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                    'type_id' => $storageManageInfo['type_id'],
                    'materiel_name' => $storageManageInfo['materiel_name'],
                    'type_name' => $storageManageInfo['type_name'],
                    'materiel_no' => $storageManageInfo['materiel_no'],
                    'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                    'storage_id' => $storageInfo['id'],
                    'storage_name' => $storageInfo['storage_name'],
                    'storage_address' => $storageInfo['storage_address'],
                    'in_storage_num' => $data['allocate_num'],
                    'virtual_storage_num' => $data['allocate_num'],
                    'alert_num' => 0,
                    'materiel_original' => 1,
                    'main_id' => $data['main_id'],
                    'in_storage_time' => time(),
                    'created_at' => time()
                ];

                //不存在相同物料时，新建物料入库信息
                $newStorageId = StorageManageModel::insertGetId($arr);
            }

            $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';

            do {
                $batchNo = $data['batch_title'].date('YmdHis', time()).mt_rand(1000, 9999).'0';
            }
            while(!empty(StorageBatchModel::where('main_id', $data['main_id'])
                ->where('batch_no', $batchNo)->first()));

            StorageBatchModel::insert([
                'batch_no' => $batchNo,
                'storage_manage_id' => $newStorageId,
                'batch_num' => $data['allocate_num'],
                'batch_left_num' => $data['allocate_num'],
                'batch_cost' => $meanCost,
                'materiel_id' => 0,
                'main_id' => $data['main_id'],
                'created_at' => time()
            ]);

            //入库操作记录日志
            LogInstorageModel::insert([
                'type' => 1,//日志类型;0:入库;1:调拨入库;2:直接入库;
                'storage_id' => $storageInfo['id'],
                'storage_name' => $storageInfo['storage_name'],
                'storage_address' => $storageInfo['storage_address'],
                'last_storage_id' => $storageManageInfo['storage_id'],
                'last_storage_name' => $storageManageInfo['storage_name'],
                'last_storage_address' => $storageManageInfo['storage_address'],
                'last_storage_manage_id' => $storageManageInfo['id'],
                'curr_storage_manage_id' => $newStorageId,
                'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                'materiel_type_id' => $storageManageInfo['type_id'],
                'materiel_name' => $storageManageInfo['materiel_name'],
                'type_name' => $storageManageInfo['type_name'],
                'materiel_no' => $storageManageInfo['materiel_no'],
                'operate_num' => $data['allocate_num'],
                'last_storage_num' => empty($checkStorageManageInfo)?0:$checkStorageManageInfo['in_storage_num'],
                'next_storage_num' => empty($checkStorageManageInfo)?$data['allocate_num']:$checkStorageManageInfo['in_storage_num'] + $data['allocate_num'],
                'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                'remark' => empty($data['remark'])?'':$data['remark'],
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'in_storage_time' => time(),
                'created_at' => time()
            ]);

            //出库操作记录日志
            LogOutstorageModel::insert([
                'type' => 1,//type;0:出库;1:调出;
                'storage_id' => $storageManageInfo['storage_id'],
                'storage_name' => $storageManageInfo['storage_name'],
                'storage_address' => $storageManageInfo['storage_address'],
                'next_storage_id' => $storageInfo['id'],
                'next_storage_name' => $storageInfo['storage_name'],
                'next_storage_address' => $storageInfo['storage_address'],
                'curr_storage_manage_id' => $storageManageInfo['id'],
                'next_storage_manage_id' => $newStorageId,
                'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                'materiel_type_id' => $storageManageInfo['type_id'],
                'materiel_name' => $storageManageInfo['materiel_name'],
                'type_name' => $storageManageInfo['type_name'],
                'materiel_no' => $storageManageInfo['materiel_no'],
                'operate_num' => $data['allocate_num'],
                'last_storage_num' => $storageManageInfo['in_storage_num'],
                'next_storage_num' => $storageManageInfo['in_storage_num'] - $data['allocate_num'],
                'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                'remark' => empty($data['remark'])?'':$data['remark'],
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'out_storage_time' => time(),
                'created_at' => time()
            ]);

            if($storageManageInfo['virtual_storage_num'] > 0) {
                StorageManageModel::where('id', $data['id'])->update([
                    'in_storage_num' => DB::raw('in_storage_num -'.$data['allocate_num']),
                    'virtual_storage_num' => DB::raw('virtual_storage_num -'.$data['allocate_num']),
                ]);
            }
            else {
                StorageManageModel::where('id', $data['id'])->update([
                    'in_storage_num' => DB::raw('in_storage_num -'.$data['allocate_num'])
                ]);
            }

            MessageService::sendOutSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['allocate_num'],
                $storageInfo['storage_name'],
                $data['allocate_num'],
                $data,
                $storageInfo['id'],
                $storageManageInfo['alert_num'],
            );

            MessageService::sendInSms(
                '无',
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data,
                $data['allocate_num'],
                empty($checkStorageManageInfo)?$data['allocate_num']:$data['allocate_num'] + $checkStorageManageInfo['in_storage_num']
            );

            $currStorageNum = $storageManageInfo['in_storage_num'] - $data['allocate_num'];

            MessageService::sendAlertSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $currStorageNum,
                $storageManageInfo['alert_num'],
                $data,
                $storageInfo['id'],
                $storageInfo['storage_name'],
                $data['allocate_num'],
            );

            MessageService::sendShortSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['allocate_num'],
                $data,
                $storageInfo['storage_name'],
                $storageInfo['id'],
            );

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('调拨'.var_export($e->getMessage(), true));
        }
    }

    //直接出库
    static public function directOutStorage($data)
    {
        //需出库物料信息
        $storageManageInfo = StorageManageModel::select(
            'a.id',
            'a.storage_id',
            'a.materiel_class_id',
            'a.type_id',
            'a.in_storage_num',
            'a.materiel_mean_cost',
            'b.class_name as materiel_class_name',
            'b.class_no as materiel_class_no',
            'c.materiel_name',
            'c.type_name',
            'c.materiel_no',
            'd.storage_name',
            'd.storage_address',
            'a.alert_num',
            'a.virtual_storage_num',
            'a.shelf_id',
            'a.location_id'
        )
        ->from('storage_manage as a')
        ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
        ->leftJoin('materiel_type as c', 'c.id', '=', 'a.type_id')
        ->leftJoin('storage as d', 'd.id', '=', 'a.storage_id')
        ->where([
            'a.id' => $data['id'],
            'a.main_id' => $data['main_id'],
            'a.delete_flag' => 0
        ])->first();

        if(empty($storageManageInfo)) {
            return ['code' => 1, 'msg' => '库存中不存在的物料，无法出库', 'data' => ''];
        }

        if($storageManageInfo['in_storage_num'] < $data['num']) {
            return ['code' => 1, 'msg' => '操作数量超出实际库存数，无法完成出库,当前库存数为:'.$storageManageInfo['in_storage_num'], 'data' => ''];
        }

        DB::beginTransaction();

        try {
            //出库操作记录日志
            LogOutstorageModel::insert([
                'type' => 2,//type;0:出库;1:调出;2:直接出库;
                'storage_id' => $storageManageInfo['storage_id'],
                'storage_name' => $storageManageInfo['storage_name'],
                'storage_address' => $storageManageInfo['storage_address'],
                'next_storage_id' => 0,
                'next_storage_name' => '',
                'next_storage_address' => '',
                'curr_storage_manage_id' => $storageManageInfo['id'],
                'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                'materiel_type_id' => $storageManageInfo['type_id'],
                'materiel_name' => $storageManageInfo['materiel_name'],
                'type_name' => $storageManageInfo['type_name'],
                'materiel_no' => $storageManageInfo['materiel_no'],
                'operate_num' => $data['num'],
                'last_storage_num' => $storageManageInfo['in_storage_num'],
                'next_storage_num' => $storageManageInfo['in_storage_num'] - $data['num'],
                'sell_price' => $storageManageInfo['materiel_mean_cost'],
                'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
                'remark' => empty($data['remark'])?'':$data['remark'],
                'main_id' => $data['main_id'],
                'user_id' => $data['user_id'],
                'out_storage_time' => time(),
                'created_at' => time(),

                'shelf_id' => $storageManageInfo['shelf_id'],
                'location_id' => $storageManageInfo['location_id'],
            ]);

            if($storageManageInfo['virtual_storage_num'] > 0) {
                StorageManageModel::where('id', $data['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$data['num']),
                        'virtual_storage_num' => DB::raw('virtual_storage_num - '.$data['num'])
                    ]);
            }
            else {
                StorageManageModel::where('id', $data['id'])
                    ->update([
                        'in_storage_num' => DB::raw('in_storage_num - '.$data['num']),
                    ]);
            }

            MessageService::sendAlertSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['num'],
                $storageManageInfo['alert_num'],
                $data,
                $storageManageInfo['storage_id'],
                $storageManageInfo['storage_name'],
                $data['num']
            );

            MessageService::sendShortSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'] - $data['num'],
                $data,
                $storageManageInfo['storage_name'],
                $storageManageInfo['storage_id']
            );

            MessageService::sendOutSms(
                $storageManageInfo['materiel_name'],
                $storageManageInfo['type_name'],
                $storageManageInfo['in_storage_num'],
                $storageManageInfo['storage_name'],
                $data['num'],
                $data,
                $storageManageInfo['storage_id'],
                $storageManageInfo['alert_num'],
            );

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('出库1'.var_export($e->getMessage(), true));
        }
    }

    static public function setAlertNum($data)
    {
        StorageManageModel::where('id', $data['id'])->update(['alert_num' => $data['alert_num']]);

        return ['code' => 0, 'msg' => 'success', 'data' => ''];
    }

    /**出库撤销回滚数量
     * @created 在 2022/01/11 10:17 创建
     * @param $allIdType 单据类型;1:报损;2:销售;
     * @param $allId 对应单据主键id
     * @return 0:商品被删除，无法撤销;1:撤销成功;
     * @author: Sun Wu
     */
    static public function cancelOut($allIdType, $allId)
    {
        $logOutInfo = LogOutstorageModel::where([
            'all_id_type' => $allIdType,
            'all_id' => $allId,
            'is_cancel' => 0
        ])->get()->toArray();

        if(!empty($logOutInfo)) {
            $item = [];
            foreach($logOutInfo as $value) {
                if(!isset($item[$value['curr_storage_manage_id']])) {
                    $item[$value['curr_storage_manage_id']] = [
                        'id' => $value['curr_storage_manage_id'],
                        'num' => $value['operate_num']
                    ];
                }
                else {
                    $item[$value['curr_storage_manage_id']]['num'] += $value['operate_num'];
                }
            }

            $logInfoId = [];
            foreach($logOutInfo as $val) {
                $logInfoId[] = $val['id'];
            }

            foreach($item as $v) {
                $checkStorageManageInfo = StorageManageModel::where([
                    'id' => $v['id'],
                    'delete_flag' => 0
                ])->first();

                if(empty($checkStorageManageInfo)) {
                    return 0;
                }

                StorageManageModel::where([
                    'id' => $v['id']
                ])
                    ->update([
                        'in_storage_num' => DB::raw("in_storage_num + ".$v['num']),
                        'virtual_storage_num' => DB::raw("virtual_storage_num + ".$v['num'])
                    ]);
            }

            LogOutstorageModel::whereIn('id', $logInfoId)->update(['is_cancel' => 1]);
            LogOutPackageModel::where([
                'all_id_type' => $allIdType,
                'all_id' => $allId
            ])->update(['is_cancel' => 1]);
        }

        return 1;
    }

    /**入库撤销回滚数量
     * @created 在 2022/01/11 10:47 创建
     * @param $allIdType 单据类型;1:报溢;2:退货;3:采购;
     * @param $allId 对应单据主键id
     * @return 0:商品被删除，无法撤销;1:撤销成功;2:库存数量不足，无法撤销;
     * @author: Sun Wu
     */
    static public function cancelIn($allIdType, $allId)
    {
        $logInInfo = LogInstorageModel::where([
            'all_id_type' => $allIdType,
            'all_id' => $allId,
            'is_cancel' => 0
        ])->get()->toArray();

        if(!empty($logInInfo)) {
            $item = [];
            foreach($logInInfo as $value) {
                if(!isset($item[$value['curr_storage_manage_id']])) {
                    $item[$value['curr_storage_manage_id']] = [
                        'id' => $value['curr_storage_manage_id'],
                        'num' => $value['operate_num']
                    ];
                }
                else {
                    $item[$value['curr_storage_manage_id']]['num'] += $value['operate_num'];
                }
            }

            $logInfoId = [];
            foreach($logInInfo as $val) {
                $logInfoId[] = $val['id'];
            }

            foreach($item as $v) {
                $checkStorageManageInfo = StorageManageModel::where([
                    'id' => $v['id'],
                    'delete_flag' => 0
                ])->first();

                if(empty($checkStorageManageInfo)) {
                    return 0;
                }

                if($checkStorageManageInfo['in_storage_num'] < $v['num']) {
                    return 2;
                }

                $storageManageInfo = StorageManageModel::where(['id' => $v['id']])
                    ->first();

                if($storageManageInfo['virtual_storage_num'] > 0) {
                    StorageManageModel::where([
                        'id' => $v['id']
                    ])
                        ->update([
                            'in_storage_num' => DB::raw("in_storage_num - ".$v['num']),
                            'virtual_storage_num' => DB::raw("virtual_storage_num - ".$v['num'])
                        ]);
                }
                else {
                    StorageManageModel::where([
                        'id' => $v['id']
                    ])
                        ->update([
                            'in_storage_num' => DB::raw("in_storage_num - ".$v['num']),
                        ]);
                }
            }

            LogInstorageModel::whereIn('id', $logInfoId)->update(['is_cancel' => 1]);
        }

        return 1;
    }
}
